/**
 * Created with CLion.
 * Description:
 * User: loong
 * Date: 2024/3/23
 * Time: 21:34
 */

#ifndef CES_BLOCKINGQUEUE_H
#define CES_BLOCKINGQUEUE_H

#include "NonCopyable.h"
#include <cassert>
#include <condition_variable>
#include <deque>
#include <mutex>
namespace CES {
    namespace Utils {

        template<typename T>
        class BlockingQueue : NonCopyable
        {
        public:
            BlockingQueue()
                : mutex_()
                , notEmpty_()
                , queue_()
            {
            }

            void Put(const T & x)
            {
                std::lock_guard<std::mutex> guard(mutex_);
                queue_.push_back(x);
                notEmpty_.notify_one();
            }

            void Put(const T && x)
            {
                std::lock_guard<std::mutex> guard(mutex_);
                queue_.push_back(std::move(x));
                notEmpty_.notify_one();
            }

            T Take()
            {
                std::unique_lock<std::mutex> lock(mutex_);
                notEmpty_.wait(lock, [=]() { return !queue_.empty(); });

                assert(!queue_.empty());
                T front(std::move(queue_.front()));
                queue_.pop_front();
                return front;
            }

            size_t Size() const
            {
                std::lock_guard<std::mutex> guard(mutex_);
                return queue_.size();
            }

            bool IsEmpty()
            {
                std::lock_guard<std::mutex> guard(mutex_);
                return queue_.empty();
            }

        private:
            mutable std::mutex      mutex_;
            std::condition_variable notEmpty_;
            std::deque<T>           queue_;
        };

    }// namespace Utils
}// namespace CES

#endif//CES_BLOCKINGQUEUE_H
